package com.grad.webstudy.controller;

import com.alibaba.fastjson.JSONObject;
import com.grad.webstudy.annota.LoginAuthorization;
import com.grad.webstudy.context.UserContext;
import com.grad.webstudy.model.User;
import com.grad.webstudy.service.MessageService;
import com.grad.webstudy.service.UserService;
import com.grad.webstudy.vo.MessageVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description:
 * @Author: zjf
 * @Date: 2020/1/29 10:46.
 */
@ServerEndpoint("/websocket/chat/{receiveId}")
@LoginAuthorization
@RestController
public class WebSocketServer {


    private static UserService userService;//由于websocket是多个对象管理，spring是单例模式，不能直接注入
    private static MessageService messageService;

    @Autowired
    public void setUserService(UserService userService) {
        WebSocketServer.userService = userService;
    }

    @Autowired
    public void setMessageService(MessageService messageService) {
        WebSocketServer.messageService = messageService;
    }


    //存储客户端的连接对象,每个客户端连接都会产生一个连接对象
    private static ConcurrentHashMap<String, WebSocketServer> map = new ConcurrentHashMap();
    //每个连接都会有自己的会话
    private Session session;

    private String messageId;//聊天id，以sendId+"-"+receiveId组合

    @OnOpen
    public void open(@PathParam("receiveId") String receiveId, Session session) {


        User loginUser = UserContext.getLoginUser();
        int userId = loginUser.getId();

//        int userId = 12;


        String messageId = userId + "-" + receiveId;
        map.put(messageId, this);
        System.out.println(messageId + "连接服务器成功");
        System.out.println("客户端连接个数:" + getConnetNum());

        this.session = session;
        this.messageId = messageId;
    }

    @OnClose
    public void close() {
        map.remove(messageId);
        System.out.println(messageId + "断开了服务器连接");
    }

    @OnError
    public void error(Throwable error) {
        error.printStackTrace();
        System.out.println(messageId + "出现了异常");
    }


    @OnMessage
    public void getMessage(String message, @PathParam("receiveId") String receiveId) throws IOException, EncodeException {
        System.out.println("收到" + messageId + ":" + message);
        System.out.println("客户端连接个数:" + getConnetNum());


        String[] newMessageIds = messageId.split("-");
        String newMessage = newMessageIds[1] + "-" + newMessageIds[0];

        MessageVo messageVo = getMessageVo(receiveId);
        messageVo.setMessage(message);
        System.out.println(messageVo);

        messageService.recordHistoryMessage(message, Integer.valueOf(receiveId));


        Set<Map.Entry<String, WebSocketServer>> entries = map.entrySet();
        for (Map.Entry<String, WebSocketServer> entry : entries) {
            if (entry.getKey().equals(newMessage)) {//将消息转发到接受者
                entry.getValue().send(messageVo);

            }
        }
    }

    public void send(MessageVo message) throws IOException {
        if (session.isOpen()) {
            //todo 待测试
            String resultMessage = JSONObject.toJSONString(message);
            System.out.println(resultMessage);
            session.getBasicRemote().sendText(resultMessage);
        }
    }

    public int getConnetNum() {
        return map.size();
    }

    private MessageVo getMessageVo(String receiveId) {

        System.out.println(receiveId);
        User receiveUser = userService.selectUserForSystem(Integer.parseInt(receiveId));
        MessageVo result = new MessageVo();
        result.setrHeadImagePath(receiveUser.getImagePath());
        result.setReceiveId(Integer.valueOf(receiveId));
        result.setReceiveUserName(receiveUser.getUsername());
        User loginUser = UserContext.getLoginUser();
        result.setSendId(loginUser.getId());
        result.setSendUserName(loginUser.getUsername());
        result.setSendUserName(loginUser.getImagePath());
        return result;
    }
}
